#include "Ville.h"


/**
 * \fn         void initVille(Ville* ville)
 * \brief      initialise les valeurs d'une ville
 * \details
 * \param      ville pointeur sur la ville à initialiser
 */
void initVille(Ville* ville)
{
  char* chaine = "Nains Trépides";
  Population* population;
  Entrepot* reserves;
  ArbreTech* arbre;

  ville->nomClan = chaine;

  creerPopulation(&population);
  ville->population = population;

  creerEntr(&reserves);
  ville->reserves = reserves;

  creerArbreTech(&arbre);
  ville->arbreTech = arbre;
}

/**
* \fn           void creerVille(Ville** ville)
* \brief        Créé une structure VilleProduction
* \details	Alloue de la mémoire à la Ville initialise ses valeurs avec initVille
* \param        ville     Pointeur sur le pointeur de la Ville à initialiser
*/
void creerVille(Ville** ville)
{
  *ville = (Ville*) malloc(sizeof(Ville));
  initVille(*ville);
}

/** 
 * \fn         void detruireVille(Ville** ville)
 * \brief      libère la mémoire prise allouée à la ville
 * \details
 * \param      ville      Pointeur sur le pointeur de la ville à détruire
 */
void detruireVille(Ville* ville)
{
  detruirePopulation(ville->population);
  detruireEntr(ville->reserves);
  detruireArbreTech(ville->arbreTech);
  free(ville);
}

/**
 * \fn         void ajouterMembresVille(Ville* ville)
 * \brief      ajoute un membre à la ville
 * \details
 * \param      ville pointeur sur la ville ciblée
 */
void ajouterMembreVille(Ville* ville)
{
  ajouterMembre(ville->population);
}

/**
 * \fn         void retirerMembresVille(Ville* ville, Personnage *personnage)
 * \brief      enleve un membre à la ville
 * \details
 * \param      ville pointeur sur la ville ciblée
 */
void retirerMembreVille(Ville* ville, Personnage *personnage)
{
  retirerMembre(ville->population, personnage);
}

/**
 * \fn         char* getNomClan(Ville* ville)
 * \brief      renvois la chaine de caracères du nom du clan
 * \details
 * \param      ville pointeur sur la ville ciblée
 */
char* getNomClan(Ville* ville)
{
  return ville->nomClan;
}

/**
 * \fn         unsigned int getEffectif()
 * \brief      renvois l'effectif actuel dans la ville
 * \details
 * \param      ville   Pointeur sur la ville
 */
unsigned int getEffectif(Ville* ville)
{
  return ville->population->effectifTotal;
}

/**
 * \fn         Entrepot* getReserves(Ville* ville)
 * \brief      Renvois un pointeur sur l'entrepot de la ville
 * \details
 * \param      ville   Pointeur sur la ville
 */
Entrepot* getReserves(Ville* ville)
{
  return ville->reserves;
}

/**
 * \fn         void setNomClan(Ville* ville, char* nouvNom)
 * \brief      attibue un nom de clan à la ville passée en argument
 * \details
 * \param      ville   Pointeur sur la ville
 * \param      nouvNom Chaine de caactère du nouveau nom
 */
void setNomClan(Ville* ville, char* nouvNom)
{
  free(ville->nomClan);
  ville->nomClan = nouvNom;
}

/**
 * \fn        void calcPrioriteComportements(Ville* ville, Personnage* personnage)
 * \brief     attribue un comportement rentable pour la ville au personnage donné en argument
 * \details
 * \param     ville   Pointeur sur la ville
 * \param     personnage Pointeur sur le personnage auquel attribuer un comportement
 */
void calcPrioriteComportements(Ville* ville, Personnage* personnage);

/**
 * \fn       unsigned int calcDepartPop(Ville* ville)
 * \brief    renvois le nombre de parsonnages quittant la ville en fonction des paramètres démographiques
 * \details
 * \param    ville   Pointeur sur la ville
 */
unsigned int calcDepartPop(Ville* ville)
{
  unsigned int effectif, nbEmigres, nbDeces;

  effectif = getEffectifTotal(ville->population);
  nbEmigres = getEmigration(ville->population) * effectif / 100;
  nbDeces = getMortalite(ville->population) * effectif / 100;

  return (nbEmigres + nbDeces);
}

/**  
 * \fn       unsigned int calcArriveesPop(Ville* ville)
 * \brief    calcule le nombre de personnage arrivant dans la ville en fonction des paramètres démographiques
 * \details
 * \param    ville   Pointeur sur la ville
 */
unsigned int calcArriveesPop(Ville* ville)
{
unsigned int effectif, nbImmigres, nbNaissances;

  effectif = getEffectifTotal(ville->population);
  nbImmigres = getImmigration(ville->population) * effectif / 100;
  nbNaissances = getFecondite(ville->population) * effectif / 100;

  return (nbImmigres + nbNaissances);
}

/**
 * \fn       unsigned int calcConsomationNourr(Ville* ville)
 * \brief    renvois la nourriture consommée par pas de temps par les personnages
 * \details
 * \param    ville   Pointeur sur la ville
 */
unsigned int calcConsomationNourr(Ville* ville);

/**
 * \fn      int calcEvolutionMoral(Ville* ville)
 * \brief   renvois l'évolution générale du morale au sein de la ville
 * \details
 * \param   ville   Pointeur sur la ville
 */
int calcEvolutionMoral(Ville* ville);

/**
* \brief	Développe une technologie dont on aura passé l'ID
* \details	Edite le champ dev de la technologie dont on a passé l'ID,
*		le tableau de prérequis des technologies qui la nécessitent
*               et les valeurs des bonus/malus induits
* \param	pAT		Pointeur vers un arbre des technologies
* \param	pSA		Pointeur vers un sous-arbre
*/
void devTechArbreTechVille(Ville* ville, ArbreTech *pAT, int IDTech)
{
  int modificateurs[8] = {0,0,0,0,0,0,0,0};
  Entrepot* entrepot;
  Population* population;

  entrepot = getReserves(ville);
  population = ville->population;

  devTechArbreTech(pAT, IDTech, modificateurs);

  if(modificateurs[2] != 0)
    setFecondite(population,modificateurs[2]);
 
  if(modificateurs[3] != 0)
    setMortalite(population,modificateurs[3]);
 
  if(modificateurs[4] != 0)
    setImmigration(population,modificateurs[4]);
 
  if(modificateurs[5] != 0)
    setEmigration(population,modificateurs[5]);

  if(modificateurs[6] != 0)
    setMoral(population,modificateurs[6]);

  if(modificateurs[7] != 0)
    ajouteModifProd(entrepot,modificateurs[7]);

}

/**
 * \fn      void incrementePasDeTemps(Ville* ville)
 * \brief   fait évoluer la ville d'un pas de temps en modifiant ses paramètres en conséquence
 * \details
 * \param    ville   Pointeur sur la ville
 */
void incrementePasDeTemps(Ville* ville)
{
  int i,j;
  int diff;
diff = calcDepartPop(ville) - calcArriveesPop(ville);


if(diff > 0)
  for(i=0;i<diff;i++)
    {
      retirerMembreVille(ville,ville->population->dernierPersonnage);
    }

if(diff < 0)
  for(j=0;j<diff;j++)
    {
      ajouterMembreVille(ville);
    }

}
